package db

import (
	"errors"
	"fmt"
	"hr/api/dto"
	"strings"

	"gorm.io/gorm"
)

type Role struct {
	AppModel
	Name     string  `gorm:"size:64" json:"name"`
	CreateBy string  `gorm:"size:128" json:"createBy"` // 创建人
	UpdateBy string  `gorm:"size:128" json:"updateBy"` // 更新人
	Remark   string  `gorm:"size:255" json:"remark"`   //备注
	Status   string  `gorm:"size:4;" json:"status"`
	Code     string  `gorm:"size:64;" json:"code"`
	Menu     []*Menu `gorm:"many2many:role_menu;" json:"menu"`
}

func (m *Role) TableName() string {
	return "role"
}

type RolePageModel struct {
	Total    int64  `json:"total"`
	Result   []Role `json:"result"`
	PageNo   int    `json:"pageNo"`
	PageSize int    `json:"pageSize"`
}

// GetRole 根据条件查找
func GetRole(p map[string]interface{}, extra ...interface{}) (Role, error, string) {
	f := Role{}
	queryDb := GetInstance().Where(p).First(&f)
	if len(extra) > 0 {
		queryDb = queryDb.Where(extra)
	}
	err := queryDb.Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return f, errors.New("查无记录"), "0"
		}
		return f, errors.New(err.Error()), "1"
	}
	return f, nil, "2"
}

// GetRoleString 根据条件查找
func GetRoleString(id, name string) (Role, error, string) {
	f := Role{}
	err := GetInstance().Where("id != ? AND name = ?", id, name).First(&f).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return f, errors.New("查无记录"), "0"
		}
		return f, errors.New(err.Error()), "1"
	}
	return f, nil, "2"
}

func GetRolePaging(pagination dto.Pagination, name string) (RolePageModel, error) {
	result := RolePageModel{
		Total:    0,
		Result:   make([]Role, 0),
		PageNo:   pagination.PageNo,
		PageSize: pagination.PageSize,
	}
	offset := (pagination.PageNo - 1) * pagination.PageSize
	dbs := GetInstance().Preload("Menu").Model(&Role{})
	if name != "" {
		dbs = dbs.Where("role.name LIKE ?", "%"+name+"%")
	}

	if err := dbs.Offset(offset).Limit(pagination.PageSize).Find(&result.Result).Error; err != nil {
		return result, err
	}
	if err := dbs.Offset(-1).Limit(-1).Count(&result.Total).Error; err != nil {
		return result, err
	}
	return result, nil
}

func CreateRole(p dto.RoleRequest, user string) (Role, error) {
	d := Role{
		Name:     p.Name,
		Code:     p.Code,
		CreateBy: user,
		Remark:   p.Remark,
	}
	tx := GetInstance().Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return d, err
	}
	if err := tx.Create(&d).Error; err != nil {
		tx.Rollback()
		return d, errors.New("创建失败")
	}
	if p.Menu != "" {
		val := make([]string, 0)
		menuList := strings.Split(p.Menu, ",")
		for i := range menuList {
			val = append(val, fmt.Sprintf("(%d,%s)", d.ID, menuList[i]))
		}
		if err := tx.Exec(fmt.Sprintf("INSERT INTO role_menu VALUES %s", strings.Join(val, ","))).Error; err != nil {
			tx.Rollback()
			return d, err
		}
	}
	tx.Commit()
	return d, nil
}

func UpdateRole(id uint, p dto.RoleRequest, userId string) (Role, error) {
	f := Role{
		AppModel: AppModel{
			ID: id,
		},
	}
	tx := GetInstance().Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return f, err
	}
	if err := GetInstance().Model(&f).Updates(Role{
		Name:     p.Name,
		Code:     p.Code,
		Remark:   p.Remark,
		UpdateBy: userId,
	}).Scan(&f).Error; err != nil {
		tx.Rollback()
		return f, err
	}

	if p.Menu != "" {
		if err := tx.Exec("DELETE FROM role_menu WHERE role_id = ?", id).Error; err != nil {
			tx.Rollback()
			return f, err
		}
		val := make([]string, 0)
		menuList := strings.Split(p.Menu, ",")
		for i := range menuList {
			val = append(val, fmt.Sprintf("(%d,%s)", id, menuList[i]))
		}
		if err := tx.Exec(fmt.Sprintf("INSERT INTO role_menu VALUES %s", strings.Join(val, ","))).Error; err != nil {
			tx.Rollback()
			return f, err
		}
	}
	tx.Commit()
	return f, nil
}

func DeleteRole(id uint) (Role, error) {
	f := Role{}
	tx := GetInstance().Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return f, err
	}
	if err := tx.Exec("DELETE FROM role_menu WHERE role_id = ?", id).Error; err != nil {
		tx.Rollback()
		return f, err
	}
	if err := tx.Unscoped().Where("id = ?", id).Delete(&f).Error; err != nil {
		tx.Rollback()
		return f, err
	}
	tx.Commit()
	return f, nil
}

func GetRoleById(id string) Role {
	role := Role{}
	GetInstance().Where("id=?", id).First(&role)
	return role
}

//有部门小队长的逻辑
func HasSmallCaptain(deptId uint) bool {
	role := Role{}
	GetInstance().Where("code='small_captain'").First(&role)
	if role.ID == 0 {
		return false
	}

	user := User{}
	GetInstance().Where("role_id=? and dept_id=?", role.ID, deptId).First(&user)
	if user.ID == 0 {
		return false
	}
	return true
}
